package cmd

import (
	"fmt"
	"gitee/kubehark/kubehark-client/pkg/config"
	"gitee/kubehark/kubehark-client/pkg/oidc"
	"github.com/spf13/cobra"
	"golang.org/x/oauth2"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/tools/clientcmd/api"
)

func NewRefereshTokenCmd() *cobra.Command {
	var Cmd = &cobra.Command{
		Use:   "refresh-token",
		Short: "get token",
		Long:  `获取apiserver对应的鉴权对象 `,
		Run: func(cmd *cobra.Command, args []string) {
			refreshToken(cmd)
		},
	}
	return Cmd
}

func refreshToken(cmd *cobra.Command) (err error) {
	var token *oauth2.Token
	var ok bool
	// 获取token
	token, err = getRefreshedToken(nil)
	if err != nil {
		return
	}

	var rawIDToken string
	rawIDToken, ok = token.Extra("id_token").(string)
	if !ok {
		return
	}
	// 构造需要返回的对象信息
	data := `
			{
			  "apiVersion": "client.authentication.k8s.io/v1beta1",
			  "kind": "ExecCredential",
			  "status": {
				"token": "%s"
			  }
			}`
	_, _ = fmt.Fprint(cmd.OutOrStdout(), string(fmt.Sprintf(data, rawIDToken)))
	return
}

func getRefreshedToken(c *api.Config) (token *oauth2.Token, err error) {
	var codeFetcher oidc.CodeFetcher
	if codeFetcher == nil {
		codeFetcher = oidc.NewBrowserFetcher()
	}

	r := clientcmd.NewDefaultClientConfigLoadingRules()
	if c == nil {
		c, err = clientcmd.LoadFromFile(r.GetDefaultFilename())
	}
	if err != nil {
		return
	}

	if err = config.Valid(c); err != nil {
		return
	}

	var oidcClientID string
	var refreshToken string
	var oidcServer string
	var oidcSecret string

	oidcSecret, err = config.GetCurrentAuthInfoEnvByName(c, "oidc-secret")
	if err != nil {
		return
	}
	oidcClientID, err = config.GetCurrentAuthInfoEnvByName(c, "oidc-client-id")
	if err != nil {
		return
	}
	refreshToken, err = config.GetCurrentAuthInfoEnvByName(c, "refresh-token")
	if err != nil {
		return
	}
	oidcServer, err = config.GetCurrentAuthInfoEnvByName(c, "oidc-server")
	if err != nil {
		return
	}
	oidcApp, err := oidc.Setup(
		oidcClientID,
		oidcServer,
		"http://127.0.0.1:5555/callback",
		oidcSecret,
	)
	token, err = oidcApp.GetToken(refreshToken)
	if err != nil {
		code := codeFetcher.Fetch(&oidcApp)
		token, err = oidcApp.Exchange(code)
	}
	err = config.SetCurrentAuthInfoEnvByName(c, "refresh-token", token.RefreshToken)
	if err != nil {
		return
	}

	if err = clientcmd.WriteToFile(*c, r.GetDefaultFilename()); err != nil {
		return
	}
	return
}
